package com.factory.code.lib.database;


import com.factory.code.common.helper.StringHelper;
import com.factory.code.controller.param.ConnectionParam;
import com.factory.code.controller.param.GeneratorDeployParam;
import com.factory.code.lib.database.model.TableColumnModel;
import com.factory.code.lib.database.model.TableInfoModel;
import com.factory.code.repository.ent.ProjectENT;
import com.factory.code.service.model.CodeContextModel;
import com.factory.code.service.model.CodeTableColumnModel;
import com.factory.code.service.model.CodeTableInfoModel;
import com.factory.code.service.model.CodeTableModel;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.List;


public abstract class DatabaseBehavior {
    protected ConnectionParam connectionParam;

    void initialize(ConnectionParam connectionParam) {
        if (null == connectionParam) {
            throw new IllegalArgumentException("connectionParam must be not null");
        }
        this.connectionParam = connectionParam;
    }

    public JdbcTemplate getJdbcTemplate() {
        return DatabaseManager.getJdbcTemplate(connectionParam);
    }

    /**
     * 获取库名
     */
    public abstract String getDbType();

    public abstract List<String> getDbDriver();

    public abstract String getDatabaseName();

    public abstract List<String> listTableName();

    /**
     * 获取所有表信息
     */
    public abstract List<TableInfoModel> getTableAll();


    /**
     * 根据表名获取列信息
     *
     * @param tableName 表名
     * @return
     */
    public abstract List<TableColumnModel> listFieldModel(String tableName);

    public abstract String getDbAttrType(String dbType);


    public CodeTableModel getTemplateModel(String tableName, GeneratorDeployParam deploy) {
        CodeContextModel contextModel = new CodeContextModel();
        contextModel.setTableName(tableName);
        String tablePrefix = StringHelper.removePrefix(tableName, deploy.getTablePrefix().split(","));
        String beanName = StringHelper.removeUnderline(tablePrefix);
        contextModel.setBeanName(beanName);
        contextModel.setPackageName(deploy.getPackageName());
        contextModel.setAuthor(deploy.getAuthor());

        List<TableColumnModel> tableColumnModels = listFieldModel(tableName);
        List<CodeTableColumnModel> list = new ArrayList<>();
        //表属性
        for (TableColumnModel tableColumnModel : tableColumnModels) {
            CodeTableColumnModel model = new CodeTableColumnModel();
            BeanUtils.copyProperties(tableColumnModel, model);

            String fieldType = getFieldType(tableColumnModel.getDataType());
            model.setAttrType(fieldType);
            String prefix = StringHelper.removePrefix(tableColumnModel.getColumnName(), deploy.getColumnPrefix().split(","));
            String attrName = StringHelper.removeUnderline(prefix);
            model.setAttrName(attrName);
            model.setComments(tableColumnModel.getComment());
            list.add(model);
        }
        CodeTableInfoModel tableInfo = new CodeTableInfoModel();


        CodeTableModel tableModel = new CodeTableModel();
        tableModel.setTableInfo(tableInfo);
        tableModel.setContext(contextModel);
        tableModel.setTableColumns(list);
        return tableModel;
    }


    protected String getFieldType(String dataType) {
        String attrType = getDbAttrType(dataType);
        if (StringUtils.isNotEmpty(attrType)) {
            return attrType;
        }
        switch (dataType.toLowerCase()) {
            case "bit":
                return "Boolean";
            case "tinyint":
            case "smallint":
            case "mediumint":
            case "int":
            case "integer":
                return "Integer";
            case "bigint":
                return "Long";
            case "double":
            case "decimal":
                return "BigDecimal";
            case "date":
            case "datetime":
                return "Date";
            case "timestamp":
                return "Timestamp";
            default:
                return "String";
        }
    }
}
